package cn.thoughtworks.school.usercenter.services;

import cn.thoughtworks.school.usercenter.entities.*;
import cn.thoughtworks.school.usercenter.feign.OrganizationCenterFeign;
import cn.thoughtworks.school.usercenter.repositories.UserDetailRepository;
import cn.thoughtworks.school.usercenter.repositories.UserRepository;
import cn.thoughtworks.school.usercenter.repositories.UserRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class OrganizationService {
  @Autowired
  private UserRoleRepository userRoleRepository;
  @Autowired
  private UserRepository userRepository;
  @Autowired
  private UserDetailRepository userDetailRepository;
  @Autowired
  private OrganizationCenterFeign organizationCenterFeign;
  @Autowired
  private UserService userService;

  public List<UserRole> findRolesByOrganizationId(Long organizationId) {
    return userRoleRepository.findByOrganizationId(organizationId);
  }

  public List<Map> getUsersByOrganizationIdAndConditions(Long organizationId, Map<String, Object> searchParam) {
    List<User> users = getUsersByConditions(searchParam);
    List<Long> ids = users.stream().map(User::getId).collect(Collectors.toList());
    ids = filterIdNotInOrganization(organizationId, ids);
    List<UserDetail> userDetails = userDetailRepository.getAllByUserIdIn(ids);
    return WrappedUser.merge(users, userDetails);
  }

  private List<Long> filterIdNotInOrganization(Long organizationId, List<Long> searchIds) {
    List<UserOrganization> userOrganizations = organizationCenterFeign.findUserOrganizationsByOrganizationId(organizationId);
    List<Long> currentOrganizationIds = userOrganizations.stream().map(UserOrganization::getUserId)
      .collect(Collectors.toList());

    return searchIds.stream().filter(currentOrganizationIds::contains).collect(Collectors.toList());
  }

  private List<User> getUsersByConditions(Map<String, Object> searchParam) {
    List<String> usernameOrEmail = (List<String>) searchParam.get("usernameOrEmail");
    return userRepository.getAllByUsernameInOrEmailIn(usernameOrEmail, usernameOrEmail);
  }

  public List<Map> getUsersByOrganizationIdAndIds(Long organizationId, String ids) {
    List<Long> idList = Arrays.stream(ids.split(","))
      .map(Long::parseLong)
      .collect(Collectors.toList());
    List<User> users = userRepository.getAllByIdIn(idList);
    List<UserRole> userRoles = userRoleRepository.findByOrganizationIdAndUserIdIn(organizationId, idList);

    return mergeUserAndUserRole(users, userRoles);
  }

  private List<Map> mergeUserAndUserRole(List<User> users, List<UserRole> userRoles) {
    return users.stream().map(user -> {
      Map<String, Object> temp = new HashMap<>();
      List<Integer> roles = userRoles.stream().filter(userRole -> userRole.getUserId().equals(user.getId()))
        .map(UserRole::getRole).collect(Collectors.toList());
      temp.put("id", user.getId());
      temp.put("username", user.getUsername());
      temp.put("email", user.getEmail());
      temp.put("roles", roles);
      return temp;
    }).collect(Collectors.toList());
  }

  public void deleteOrganizationUserRole(Long organizationId, Long userId, Integer roleNumber) {
    userService.deleteOrganizationUserRole(organizationId, userId, roleNumber);
  }


  public List<Map> getOrganizationsById(Long userId) {
    return organizationCenterFeign.getOrganizationsById(userId);
  }

  public List getAdminsRoleByOrganizationId(Long organizationId) {
    Integer ADMIN_ROLE = 9;
    List<UserRole> userRoles = userRoleRepository.findByOrganizationIdAndRole(organizationId,ADMIN_ROLE);
    List<Long> ids = userRoles.stream().map(UserRole::getUserId).collect(Collectors.toList());
    List<User> users = userRepository.getAllByIdIn(ids);

    return mergeUserAndUserRole(users, userRoles);
  }
}